package com.xinQing.blogme.conf.security;

import com.xinQing.blogme.util.Check;
import com.xinQing.blogme.util.Response;
import com.xinQing.blogme.util.Result;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * Created by null on 2017/8/2.
 */
@Slf4j
public class JWTTokenManager {

    private final long EXPIRATION_TIME = 432_000_000;     // 5天
    private final String SECRET = "P@ssw02d";            // JWT密码
    private final String TOKEN_PREFIX = "Bearer";        // Token前缀
    private final String HEADER_STRING = "Authorization";// 存放Token的Header Key

    @Setter
    private UserDetailsService userDetailsService;

    public void addAuthentication(HttpServletResponse response, String username) {
        // 生成JWT
        String JWT = Jwts.builder()
                // 保存权限（角色）
                .claim("roles", "ROLE_ADMIN,ROLE_USER")
                // 用户名写入标题
                .setSubject(username)
                // 有效期设置
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                // 签名设置
                .signWith(SignatureAlgorithm.HS512, SECRET)
                .compact();
        // 将 JWT 写入 body
        try {
            Response.writeJsonAndFlush(response, Result.ok("登录认证成功，data字段为jwt", JWT));
        } catch (IOException e) {
            log.warn("{}", e);
        }
    }

    public Authentication getAuthentication(HttpServletRequest request) {
        // 从Header中拿到token
        String token = request.getHeader(HEADER_STRING);
        if (Check.isNotEmpty(token)) {
            // 解析 Token
            Claims claims = Jwts.parser()
                    // 验签
                    .setSigningKey(SECRET)
                    // 去掉 Bearer
                    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                    .getBody();
            // 拿用户名
            String username = claims.getSubject();
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            return getAuthentication(userDetails);
        }
        return null;
    }

    private UsernamePasswordAuthenticationToken getAuthentication(UserDetails userDetails) {
        return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(),
                userDetails.getAuthorities());
    }
}